unit debugs;

{*
Simple debuging unit
You can mask or unmask which kind of messages do you want to display
You can also change debuging level from command line, e.g. -dlBegin -dlParam -dlCustom3
}

interface

uses SysUtils;

const
  // Debug levels
  dlBegin = 1;        // some block begin (e.g. function)
  dlEnd = 2;          // some block end (e.g. function)
  dlParam = 4;        // function parameters
  dlOther = 8;        // other level (most used)
  dlInput = 16;       // key, mouse or other input events
  dlDetail = 32;      // often displayed Items, so they must be filtered
  dlCustom1 = 64;     // custom level 1
  dlCustom2 = 128;    // custom level 2
  dlCustom3 = 256;    // custom level 3
  dlCustom4 = 512;    // custom level 4
  dlInfo = 1024;      // information which should be dislayed, it's not Debug informations
  dlNet = 2048;       // network debug infos, e.g. received packets
  dlNetDetail = 4096; // network debug details, e.g. packet datas

  dlNone = dlInfo;    // no Debug messages
  dlAll = dlBegin+dlEnd+dlParam+dlOther+dlInput+dlDetail+dlCustom1+dlCustom2+dlCustom3+dlCustom4+dlInfo+dlNet+dlNetDetail; 

type
  TDebug = class
  private
    FMask: integer;
  public
    constructor Create; virtual;
    procedure Msg(ALevel: integer; AMessage: string);
    procedure MsgN(ALevel: integer; AMessage: string);
    procedure Enable(ALevel : integer);
    procedure Disable(ALevel : integer);
  published
    property Mask: integer read FMask write FMask;
  end;

var
  Debug: TDebug;

implementation

constructor TDebug.Create;
{*
Set initial debuging level and override it from command line if it is present
}
var 
  i : integer;
  s : string;
begin
  FMask := dlInfo;
  for i := 1 to ParamCount do
  begin  
    s := LowerCase(ParamStr(i));
    if s='-dlbegin' then Enable(dlBegin);
    if s='-dlend' then Enable(dlEnd);
    if s='-dlparam' then Enable(dlParam);
    if s='-dlother' then Enable(dlOther);
    if s='-dlinput' then Enable(dlInput);
    if s='-dldetail' then Enable(dlDetail);
    if s='-dlcustom1' then Enable(dlCustom1);
    if s='-dlcustom2' then Enable(dlCustom2);
    if s='-dlcustom3' then Enable(dlCustom3);
    if s='-dlcustom4' then Enable(dlCustom4);
    if s='-dlinfo' then Enable(dlInfo);
    if s='-dlnet' then Enable(dlNet);
    if s='-dlnetdetail' then Enable(dlNetDetail);
    if s='-dlall' then Enable(dlAll);
  end;
end;

procedure TDebug.Msg(ALevel: integer; AMessage: string);
{*
Print debug message if ALevel is in current debug mask
}
begin
  {$IFNDEF NO_CONSOLE}
  if (FMask and ALevel) > 0 then
    if (FMask and dlInfo) = dlInfo then
      WriteLn(AMessage)
    else
      WriteLn('[', ALevel: 2, '] ', AMessage);
  {$ENDIF}
end;

procedure TDebug.MsgN(ALevel: integer; AMessage: string);
{*
Print debug message if ALevel is in current debug mask - but do not go to new line
}
begin
  {$IFNDEF NO_CONSOLE}
  if (FMask and ALevel) > 0 then
    if (FMask and dlInfo) = dlInfo then
      Write(AMessage)
    else
      Write('[', ALevel: 2, '] ', AMessage);
  {$ENDIF}
end;

procedure TDebug.Enable(ALevel : integer);
{*
Enable displaying messages from given level
}
begin
  Mask := Mask or ALevel;
end;

procedure TDebug.Disable(ALevel : integer);
{*
Disable displaying messages from given level
}
begin
  Mask := Mask and not ALevel;
end;

initialization

  Debug := TDebug.Create;

finalization

  Debug.Msg(dlInfo,'Releasing Debug');
  Debug.Free;

end.
